﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.Exceptions;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Controls;
using YArchitech.DataModel;
using YArchitech.LIB;
using YArchitech.MEP;
using YArchitech.Revit;

namespace YArchitech.Plumbing
{
	[Transaction(TransactionMode.Manual)]
	[Regeneration(RegenerationOption.Manual)]
	public class LayFireHydrant : IExternalCommand
	{
		public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
		{
			Transaction transaction = null;
			Result result;
			try
			{
				if (commandData == null)
				{
					throw new System.ArgumentNullException();
				}
				UIApplication application = commandData.Application;
				UIDocument activeUIDocument = application.ActiveUIDocument;
				Document document = activeUIDocument.Document;
				Selection selection = activeUIDocument.Selection;
				if (!YJKRevitTools.ViewCheck(activeUIDocument, new List<ViewType>
				{
					(ViewType)1,
					(ViewType)2,
					(ViewType)4
				}))
				{
					result = Autodesk.Revit.UI.Result.Cancelled;
				}
				else
				{
					for (;;)
					{
						HYEquipmentCommon hyequipmentCommon = new HYEquipmentCommon();
						ICollection<ElementId> allFamilyInstance = hyequipmentCommon.GetAllFamilyInstance(document, BuiltInCategory.OST_MechanicalEquipment);
						SpaceFamilyDataReader spaceFamilyDataReader = new SpaceFamilyDataReader();
						FormLayFireHydrant formLayFireHydrant = new FormLayFireHydrant(document);
						DialogResult dialogResult = formLayFireHydrant.ShowDialog();
						if (dialogResult == DialogResult.OK)
						{
							FireHydrantParam fireHydrantParam = formLayFireHydrant.fireHydrantParam;
							FamilySymbol familySymbol = formLayFireHydrant.fs;
							if (familySymbol == null)
							{
								familySymbol = spaceFamilyDataReader.GetFamilySymbolById(fireHydrantParam.Id, "Hydrant", fireHydrantParam.SymbolName, document, BuiltInCategory.OST_MechanicalEquipment);
							}
							if (familySymbol == null)
							{
								YJKMessageBox.Information("没有获取到该型号的族");
							}
							else
							{
								this.layfs(activeUIDocument, selection, familySymbol, document, formLayFireHydrant.LayType);
								ICollection<ElementId> allFamilyInstance2 = hyequipmentCommon.GetAllFamilyInstance(document, BuiltInCategory.OST_MechanicalEquipment);
								new List<ElementId>();
								foreach (ElementId item in allFamilyInstance.Intersect(allFamilyInstance2))
								{
									allFamilyInstance2.Remove(item);
								}
								transaction = new Transaction(document, "设置消火栓的参数");
								transaction.Start();
								new AuxiliaryLineOperate();
								foreach (ElementId elementId in allFamilyInstance2)
								{
									Element elementById = document.GetElementById(elementId);
									HYParametersSetting hyparametersSetting = new HYParametersSetting(application);
									Parameter parameter = elementById.GetParameter("保护半径");
									if (parameter == null)
									{
										hyparametersSetting.SetHydrantRudioShareParam();
										parameter = elementById.GetParameter("保护半径");
									}
									if (parameter != null)
									{
										parameter.Set(UnitConvert.CovertToAPI(fireHydrantParam.Radius * 1000.0, (Autodesk.Revit.DB.DisplayUnitType)2));
									}
									if (formLayFireHydrant.LayType == 2)
									{
										double num = 0.0;
										if (document.ActiveView.GenLevel != null)
										{
											num = document.ActiveView.GenLevel.Elevation;
										}
										elementById.GetParameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM).Set(UnitConvert.CovertToAPI(fireHydrantParam.OffSet * 1000.0, (Autodesk.Revit.DB.DisplayUnitType)2) + num);
									}
									else
									{
										Parameter parameter2 = null;
										Parameter parameter3 = null;
										double num2 = 0.0;
										if (elementById.GetParameter(BuiltInParameter.INSTANCE_ELEVATION_PARAM) != null)
										{
											parameter3 = elementById.GetParameter(BuiltInParameter.INSTANCE_ELEVATION_PARAM);
										}
										else
										{
											Parameter parameter4 = elementById.GetParameter(BuiltInParameter.FAMILY_LEVEL_PARAM);
											if (parameter4 != null)
											{
												parameter4.Set(document.ActiveView.GenLevel.Id);
											}
										}
										if (parameter3 != null)
										{
											parameter3.Set(UnitConvert.CovertToAPI(fireHydrantParam.OffSet * 1000.0, (Autodesk.Revit.DB.DisplayUnitType)2));
											num2 = parameter3.AsDouble();
										}
										if (num2 != UnitConvert.CovertToAPI(fireHydrantParam.OffSet * 1000.0, (Autodesk.Revit.DB.DisplayUnitType)2))
										{
											if (elementById.GetParameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM) != null)
											{
												parameter2 = elementById.GetParameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM);
											}
											if (parameter2 != null)
											{
												parameter2.Set(UnitConvert.CovertToAPI(fireHydrantParam.OffSet * 1000.0, (Autodesk.Revit.DB.DisplayUnitType)2));
											}
										}
									}
									CreateProtectRange createProtectRange = new CreateProtectRange();
									if (fireHydrantParam.Range && (int)document.ActiveView.ViewType != 4)
									{
										List<Element> collection = new List<Element>
										{
											elementById
										};
										createProtectRange.CreatActiveViewDetailCurve(document, collection, this.hyGPS);
									}
									document.Regenerate();
								}
								transaction.Commit();
							}
						}
						else if (dialogResult == DialogResult.Cancel)
						{
							break;
						}
					}
					result = Autodesk.Revit.UI.Result.Succeeded;
				}
			}
			catch (Autodesk.Revit.Exceptions.OperationCanceledException)
			{
				result = Autodesk.Revit.UI.Result.Succeeded;
			}
			catch (Exception ex)
			{
				message = ex.Message;
				result = Autodesk.Revit.UI.Result.Failed;
			}
			finally
			{
				if (transaction != null && (int)transaction.GetStatus() != 3)
				{
					transaction.RollBack();
				}
			}
			return result;
		}

		private void layfs(UIDocument uiDoc, Selection sel, FamilySymbol familySymbol, Autodesk.Revit.DB.Document doc, int type)
		{
			if (type == 1)
			{
				try
				{
					this.freeLay(uiDoc, sel, familySymbol, doc);
					return;
				}
				catch (Autodesk.Revit.Exceptions.OperationCanceledException)
				{
					return;
				}
			}
			for (;;)
			{
				Transaction transaction = null;
				try
				{
					transaction = new Transaction(doc, "new Family");
					transaction.Start();
					this.wallLay(uiDoc, sel, familySymbol, doc);
					transaction.Commit();
					continue;
				}
				catch (Autodesk.Revit.Exceptions.OperationCanceledException)
				{
					if (transaction != null && (int)transaction.GetStatus() != 3)
					{
						transaction.Commit();
					}
				}
				break;
			}
		}

		private void wallLay(UIDocument uiDoc, Selection sel, FamilySymbol familySymbol, Autodesk.Revit.DB.Document doc)
		{
			XYZ xyz = new XYZ();
			Transform trans = null;
			Curve curve = new FireHydrantByWall(uiDoc).SelectWallAndColumn(trans, ref xyz);
			if (curve == null)
			{
				YJKMessageBox.Information("没有选到墙或柱边线，请将鼠标放到墙或柱边线上，亮显后再确定！");
				return;
			}
			using (FireHydrantJig fireHydrantJig = new FireHydrantJig(uiDoc, curve))
			{
				fireHydrantJig.StartXYZ = xyz;
				fireHydrantJig.GetEndPoint(sel);
				if (familySymbol != null && !familySymbol.IsActive)
				{
					familySymbol.Activate();
				}
				XYZ rightDirection = this.getRightDirection(curve.GetEndPoint(0), curve.GetEndPoint(1));
				FamilyInstance familyInstance = doc.Create.NewFamilyInstance(xyz, familySymbol, (Autodesk.Revit.DB.Structure.StructuralType)0);
				ElementTransformUtils.RotateElement(doc, familyInstance.Id, new YJKLine(xyz, xyz + new XYZ(0.0, 0.0, 1.0)).Line, rightDirection.AngleTo(new XYZ(1.0, 0.0, 0.0)));
				doc.Regenerate();
				if (familyInstance.HandOrientation.AngleTo(rightDirection) > 0.001)
				{
					ElementTransformUtils.RotateElement(doc, familyInstance.Id, new YJKLine(xyz, xyz + new XYZ(0.0, 0.0, 1.0)).Line, -2.0 * rightDirection.AngleTo(new XYZ(1.0, 0.0, 0.0)));
					doc.Regenerate();
				}
				List<ElementId> list = new List<ElementId>();
				list.Add(familyInstance.Id);
				if (fireHydrantJig.location == FireHydrantLocation.FHL_DOWNRIGHT)
				{
					Plane plane = RevitVersionFuncs.CreatePlanByNormalAndOrigin(familyInstance.HandOrientation, xyz);
					RevitVersionFuncs.MirrorElements(doc, list, plane, BuiltInCategory.OST_MechanicalEquipment, false);
				}
				else if (fireHydrantJig.location == FireHydrantLocation.FHL_UPRIGHT)
				{
					Plane plane2 = RevitVersionFuncs.CreatePlanByNormalAndOrigin(familyInstance.HandOrientation, xyz);
					Plane plane3 = RevitVersionFuncs.CreatePlanByNormalAndOrigin(familyInstance.FacingOrientation, xyz);
					List<ElementId> list2 = RevitVersionFuncs.MirrorElements(doc, list, plane2, BuiltInCategory.OST_MechanicalEquipment, false);
					if (list2.Count == 0)
					{
						list2 = list;
					}
					RevitVersionFuncs.MirrorElements(doc, list2, plane3, BuiltInCategory.OST_MechanicalEquipment, false);
				}
				else if (fireHydrantJig.location == FireHydrantLocation.FHL_UPLEFT)
				{
					Plane plane4 = RevitVersionFuncs.CreatePlanByNormalAndOrigin(familyInstance.FacingOrientation, xyz);
					RevitVersionFuncs.MirrorElements(doc, list, plane4, BuiltInCategory.OST_MechanicalEquipment, false);
				}
			}
		}

		private XYZ getRightDirection(XYZ startPoint, XYZ endPoint)
		{
			if ((startPoint - endPoint).X > 0.0)
			{
				return (startPoint - endPoint).Normalize();
			}
			if ((startPoint - endPoint).X != 0.0)
			{
				return -(startPoint - endPoint).Normalize();
			}
			if ((startPoint - endPoint).Y <= 0.0)
			{
				return (endPoint - startPoint).Normalize();
			}
			return (startPoint - endPoint).Normalize();
		}

		private void freeLay(UIDocument uiDoc, Selection sel, FamilySymbol familySymbol, Autodesk.Revit.DB.Document doc)
		{
			uiDoc.PromptForFamilyInstancePlacement(familySymbol);
		}

		private HyRangeCheckMajor hyGPS;
	}
}
